/**
 * @file debug.cpp
 * @brief 统一串口调试输出管理实现
 */

#include "debug.h"
#include "config.h"  // 添加配置相关的头文件
#include <stdarg.h>
#include <string.h>

// 上次各级别日志输出时间
static uint32_t lastLogTime[LOG_LEVEL_COUNT] = {0};

// 用于存储消息ID和上次输出时间的结构体
typedef struct {
    char msgId[32];  // 消息ID
    uint32_t lastTime;  // 上次输出时间
} DebugMsgRecord;

// 存储最近消息记录的数组（简单的LRU缓存）
#define MAX_DEBUG_MSG_RECORDS 20
static DebugMsgRecord debugMsgRecords[MAX_DEBUG_MSG_RECORDS] = {0};
static int nextRecordIndex = 0;  // 下一个要使用的记录索引

// 是否在重启后强制输出一次日志
static bool forceLogOnRestart = true;
static bool isFirstLog[LOG_LEVEL_COUNT] = {true, true, true, true};

// 日志级别对应的标签
const char* LOG_LEVEL_TAGS[LOG_LEVEL_COUNT] = {
    LOG_ERROR_TAG,
    LOG_WARNING_TAG,
    LOG_INFO_TAG,
    LOG_DEBUG_TAG
};

// 日志级别对应的输出间隔
const uint32_t LOG_LEVEL_INTERVALS[LOG_LEVEL_COUNT] = {
    LOG_ERROR_INTERVAL,
    LOG_WARNING_INTERVAL,
    LOG_INFO_INTERVAL,
    LOG_DEBUG_INTERVAL
};

void initDebug() {
    // 初始化上次日志输出时间
    uint32_t currentTime = millis();
    for (int i = 0; i < LOG_LEVEL_COUNT; i++) {
        lastLogTime[i] = currentTime;
    }
    
    // 输出初始化信息
    logDebugWithInterval(0, "debug_init", "[调试系统] 初始化完成");
}

bool logPrintf(LogLevel level, const char* format, ...) {
    // 获取当前时间
    uint32_t currentTime = millis();
    
    // 检查是否需要输出（时间间隔控制）
    bool shouldOutput = false;
    
    // 如果是首次输出且启用了强制输出，则输出
    if (isFirstLog[level] && forceLogOnRestart) {
        shouldOutput = true;
        isFirstLog[level] = false;
    } 
    // 否则检查时间间隔
    else if (currentTime - lastLogTime[level] >= LOG_LEVEL_INTERVALS[level]) {
        shouldOutput = true;
    }
    
    // 如果不需要输出，直接返回
    if (!shouldOutput) {
        return false;
    }
    
    // 更新上次输出时间
    lastLogTime[level] = currentTime;
    
    // 输出日志级别标签
    Serial.print(LOG_LEVEL_TAGS[level]);
    
    // 格式化输出日志内容
    char buffer[256]; // 缓冲区大小可以根据需要调整
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    
    // 输出格式化后的内容
    Serial.println(buffer);
    
    return true;
}

bool logError(const char* format, ...) {
    // 格式化日志内容
    char buffer[256];
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    
    // 调用通用日志输出函数
    return logPrintf(LOG_ERROR, "%s", buffer);
}

bool logWarning(const char* format, ...) {
    // 格式化日志内容
    char buffer[256];
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    
    // 调用通用日志输出函数
    return logPrintf(LOG_WARNING, "%s", buffer);
}

bool logInfo(const char* format, ...) {
    // 格式化日志内容
    char buffer[256];
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    
    // 强制输出日志（不检查时间间隔）
    uint32_t currentTime = millis();
    lastLogTime[LOG_INFO] = currentTime;
    
    // 输出日志级别标签
    Serial.print(LOG_LEVEL_TAGS[LOG_INFO]);
    
    // 输出格式化后的内容
    Serial.println(buffer);
    
    return true;
}

bool logDebug(const char* format, ...) {
    // 格式化日志内容
    char buffer[256];
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    
    // 调用通用日志输出函数
    return logPrintf(LOG_DEBUG, "%s", buffer);
}

bool logForce(LogLevel level, const char* format, ...) {
    // 格式化日志内容
    char buffer[256];
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    
    // 强制输出日志（不检查时间间隔）
    uint32_t currentTime = millis();
    lastLogTime[level] = currentTime;
    
    // 输出日志级别标签
    Serial.print(LOG_LEVEL_TAGS[level]);
    
    // 输出格式化后的内容
    Serial.println(buffer);
    
    return true;
}

void setForceLogOnRestart(bool enable) {
    forceLogOnRestart = enable;
}

const char* getLogLevelTag(LogLevel level) {
    if (level >= 0 && level < LOG_LEVEL_COUNT) {
        return LOG_LEVEL_TAGS[level];
    }
    return "";
}

uint32_t getLogLevelInterval(LogLevel level) {
    if (level >= 0 && level < LOG_LEVEL_COUNT) {
        return LOG_LEVEL_INTERVALS[level];
    }
    return 0;
}

/**
 * @brief 查找消息ID的记录
 * 
 * @param msgId 消息ID
 * @return int 记录索引，如果未找到则返回-1
 */
static int findMsgRecord(const char* msgId)
{
    for (int i = 0; i < MAX_DEBUG_MSG_RECORDS; i++) {
        if (strcmp(debugMsgRecords[i].msgId, msgId) == 0) {
            return i;
        }
    }
    return -1;
}

bool logDebugWithInterval(uint32_t interval, const char* msgId, const char* format, ...)
{
    // 获取当前时间
    uint32_t currentTime = millis();
    
    // 查找消息记录
    int recordIndex = findMsgRecord(msgId);
    
    // 如果找到记录，检查时间间隔
    if (recordIndex >= 0) {
        uint32_t lastTime = debugMsgRecords[recordIndex].lastTime;
        // 安全计算时间差，处理溢出情况
        uint32_t timeDiff = (currentTime >= lastTime) ? 
                           (currentTime - lastTime) : 
                           (0xFFFFFFFF - lastTime + currentTime + 1);
        
        // 如果时间间隔不够大，抑制输出
        if (timeDiff < interval) {
            return false;
        }
        
        // 更新记录的时间
        debugMsgRecords[recordIndex].lastTime = currentTime;
    } else {
        // 如果没有找到记录，创建新记录
        strncpy(debugMsgRecords[nextRecordIndex].msgId, msgId, sizeof(debugMsgRecords[nextRecordIndex].msgId) - 1);
        debugMsgRecords[nextRecordIndex].msgId[sizeof(debugMsgRecords[nextRecordIndex].msgId) - 1] = '\0'; // 确保字符串结束
        debugMsgRecords[nextRecordIndex].lastTime = currentTime;
        
        // 更新下一个记录索引（循环使用数组）
        nextRecordIndex = (nextRecordIndex + 1) % MAX_DEBUG_MSG_RECORDS;
    }
    
    // 格式化日志内容
    char buffer[256];
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    
    // 输出日志级别标签
    Serial.print(LOG_LEVEL_TAGS[LOG_DEBUG]);
    
    // 输出格式化后的内容
    Serial.println(buffer);
    
    return true;
}

/**
 * @brief LED数值链调试输出函数
 * @param bandIndex 当前频段索引
 * @param bandsCount 总频段数
 * @param targetBands 目标频段值数组
 * @param smoothedValue 平滑后的值
 * @param displayHeight LED显示高度
 * @param segmentSize 每段LED数量
 */
void debugLEDValueChain(int bandIndex, int bandsCount, float* targetBands, 
                       float smoothedValue, int displayHeight, int segmentSize)
{
#if DEBUG_SERIAL_ADC
    static uint32_t lastDetailedDebugTime = 0;
    uint32_t currentTime = millis();
    
    // 每5秒输出一次详细调试信息
    if (currentTime - lastDetailedDebugTime > 10000) {
        
        if (bandIndex == 0) {
            Serial.println("================== 频段分配调试输出 ==================");
            
            // ==================== 系统状态信息 ====================
            Serial.printf("[内存] 剩余: %d bytes, 使用率: %.1f%%\n", 
                         esp_get_free_heap_size(), 
                         100.0f * (1.0f - (float)esp_get_free_heap_size() / (float)heap_caps_get_total_size(MALLOC_CAP_8BIT)));
            
            // 简化的CPU占用率估算
            static float cpuUsagePercent = 50.0f;
            uint32_t freeHeap = esp_get_free_heap_size();
            uint32_t totalHeap = heap_caps_get_total_size(MALLOC_CAP_8BIT);
            float memoryUsage = 100.0f * (1.0f - (float)freeHeap / (float)totalHeap);
            cpuUsagePercent = 25.0f + memoryUsage * 0.8f + 15.0f; // 基础负载 + 内存负载 + FFT负载
            cpuUsagePercent = constrain(cpuUsagePercent, 20.0f, 85.0f);

            Serial.printf("[频率] CPU: %d MHz, CPU占用率: %.1f%%, 采样率: %d Hz, FFT大小: %d\n",
                          getCpuFrequencyMhz(), cpuUsagePercent, I2S_SAMPLE_RATE, SAMPLES);

            // ==================== 频段分配信息 ====================
            Serial.println("--------------------------------------------------------");
            
            // 计算配置的频段分配占比
            int configBassBands = g_config.bassBands;
            int configMidBands = g_config.midBands;
            int configHighMidBands = g_config.highMidBands;
            int configHighBands = g_config.highBands;
            int configTotalBands = configBassBands + configMidBands + configHighMidBands + configHighBands;
            
            // 按照配置占比计算实际LED条对应的频段数量
            int actualLowBands = (configBassBands * bandsCount) / configTotalBands;
            int actualMidBands = (configMidBands * bandsCount) / configTotalBands;
            int actualHighMidBands = (configHighMidBands * bandsCount) / configTotalBands;
            int actualHighBands = bandsCount - actualLowBands - actualMidBands - actualHighMidBands; // 剩余的全部给高频
            
            Serial.printf("[频段分配] 低音: %d段, 中音: %d段, 中高频: %d段, 高频: %d段, 总计: %d段\n",
                         configBassBands, configMidBands, configHighMidBands, configHighBands, configTotalBands);
            Serial.printf("[实际分配] 低音: %d段, 中音: %d段, 中高频: %d段, 高频: %d段, 总计: %d段\n",
                         actualLowBands, actualMidBands, actualHighMidBands, actualHighBands, 
                         actualLowBands + actualMidBands + actualHighMidBands + actualHighBands);
            
            // 显示分配占比
            Serial.printf("[分配占比] 低音: %.1f%%, 中音: %.1f%%, 中高频: %.1f%%, 高频: %.1f%%\n",
                         (float)actualLowBands * 100.0f / bandsCount,
                         (float)actualMidBands * 100.0f / bandsCount,
                         (float)actualHighMidBands * 100.0f / bandsCount,
                         (float)actualHighBands * 100.0f / bandsCount);
            
            // ==================== 配置参数汇总 ====================
            Serial.println("--------------------------------------------------------");
            Serial.println("[当前配置参数]");
            Serial.printf("  低频补偿: %.0f%%, 中频补偿: %.0f%%, 中高频补偿: %.0f%%, 高频补偿: %.0f%%\n",
                         g_config.lowFreqComp * 100, g_config.midFreqComp * 100, 
                         g_config.highMidFreqComp * 100, g_config.highFreqComp * 100);
            Serial.printf("  低频噪声: %.0f%%, 中频噪声: %.0f%%, 中高频噪声: %.0f%%, 高频噪声: %.0f%%\n",
                         g_config.lowFreqNoise * 100, g_config.midFreqNoise * 100, 
                         g_config.highMidFreqNoise * 100, g_config.highFreqNoise * 100);
            Serial.printf("  频谱平滑: %.0f%%, 上升速度: %.0f%%, 下降速度: %.0f%%\n",
                         g_config.spectrumSmoothing * 100, g_config.riseSpeed * 100, g_config.fallSpeed * 100);
            Serial.printf("  峰值衰减: %.0f%%, 对数尺度: %.0f%%, 频谱压缩: %.0f%%\n",
                         g_config.peakDecay * 100, g_config.logScale * 100, g_config.spectrumCompression * 100);
            
            // ==================== FFT窗函数信息 ====================
            const char* windowNames[] = {"Rectangle", "Hamming", "Hann", "Blackman"};
            Serial.printf("  FFT窗函数: %d (%s)\n", 
                         g_config.fftWindowType, 
                         (g_config.fftWindowType < 4) ? windowNames[g_config.fftWindowType] : "Unknown");
            Serial.println("================== 频段分配调试输出 ==================");
        }
        
        lastDetailedDebugTime = currentTime;
    }
#endif // DEBUG_SERIAL_ADC
}